home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
telecomm
/
sticpsrc.lzh
/
SOURCE.ARC
/
SCCVEC.S
< prev
next >
Wrap
Text File
|
1989-03-20
|
6KB
|
174 lines
/
/ SCC interrupt handler for Atari ST
/
/ exported functions and variables
/
.globl sccvec_,sccnovec_
.globl scctvec_,sccotvec_,scctim_
/
/ variables from C
/
.globl sccvecloc_,sccmaxvec_,sccpolltab_,sccchan_
.globl sccisrloc_,sccisrbit_,sccgpiploc_,sccgpipbit_
/
.shri
/
/ sccvec is the interrupt handler for SCC interrupts using INTACK
/
sccvec_:
movem.l ${d0-d2,a0-a2},-(sp) / Save C working registers
/
/ Determine if an interrupt request is really coming in from SCC
/
movea.l sccgpiploc_,a0 / Location of GPIP register
move.w sccgpipbit_,d0 / Bit number to test
btst d0,(a0) / Test bit in GPIP data register
bne.s clrisr / No interrupt, clear ISR & iret
/
/ Read SCC interrupt vector and check it
/
sccint: movea.l sccvecloc_,a0
move.b $0xff,(a0) / Generate INTACK
bra delay / Short delay
delay:
move.b (a0),d0 / Read the vector
cmp.b sccmaxvec_,d0 / Check for a legal vector
bhs.s panic / It should not be >= the maximum
/
/ Extract channel number and status from vector. Determine handler address.
/
move.b d0,d1 / Save vector to retrieve status
lsr.b $1,d0 / Discard least significant bit
bcs.s panic / It should not be a 1
andi.w $0x7c,d0 / Isolate channel number (and make word)
eori.w $0x04,d0 / Toggle A/B channel bit
lea sccchan_,a0 / Address SCC channel table
movea.l 0(a0,d0),a0 / Read address of channel structure
move.l a0,d0 / Make sure this is an attached channel
beq.s panic / No channel struct, problems...
andi.w $0x06,d1 / Isolate status info from vector
lsl.w $1,d1 / Make index in LONG array
movea.l 0(a0,d1),a1 / Read the interrupt handler address
/
/ Call the handler (defined in C), with sccchan struct as a parameter
/
move.l a0,-(sp) / Put channel struct as a parameter
jsr (a1) / Call the handler
movea.l (sp)+,a0 / Get channel struct back
/ Assumes C routine does not change it
/
/ Reset highest priority interrupt
/
movea.l 16(a0),a1 / Get control register address
move.b $0x38,(a1) / "Reset Highest IUS" opcode to WR0
/
/ Clear the ISR bit in the MFP
/
clrisr: movea.l sccisrloc_,a0 / Location of ISR
move.w sccisrbit_,d0 / Bit number to clear
bclr d0,(a0) / Clear the bit
/
/ Determine if more interrupt requests are coming in from the SCCs
/
movea.l sccgpiploc_,a0 / Location of GPIP register
move.w sccgpipbit_,d0 / Bit number to test
btst d0,(a0) / Test bit in GPIP data register
beq.s sccint / Is active, handle next SCC interrupt
/
/ Restore registers and return from interrupt handler
/
iret: movem.l (sp)+,${d0-d2,a0-a2} / Restore registers
rte
/
/ Branch to here when irrecoverable errors occur in the interrupt handler
/
panic: illegal / This will cause a TRAP
movea.l sccisrloc_,a0 / On continuation, clear it and return
move.w sccisrbit_,d0 / Bit number to clear
bclr d0,(a0) / Clear the bit
bra iret
/
/
/ sccnovec is the interrupt handler for SCC interrupts using polling
/
sccnovec_:
movem.l ${d0-d2,a0-a2},-(sp) / Save C working registers
/
/ Determine if an interrupt request is really coming in from SCC
/
movea.l sccgpiploc_,a0 / Location of GPIP register
move.w sccgpipbit_,d0 / Bit number to test
btst d0,(a0) / Test bit in GPIP data register
bne.s clrisrnv / No interrupt, clear ISR & iret
/
/ Find the SCC generating the interrupt by polling all attached SCCs
/ reading RR3A (the interrupt pending register)
/
sccintnv:
movea.l $sccpolltab_,a0 / Point to polling table
sccpoll:
move.l (a0)+,d0 / Get chan A CTRL address
beq.s panic / End of table, we did not find it!
movea.l d0,a1 / Move it to an address register
movea.l (a0)+,a2 / Also read B CTRL address
move.b $3,(a1) / Select RR3A
move.b (a1),d0 / Read it and test for 0
beq.s sccpoll / No interrupt here, try next chip
/
/ Read SCC interrupt vector from RR2B, it should always be correct
/ Extract channel number and status from vector. Determine handler address.
/
move.b $2,(a2) / Select RR2B
move.b (a2),d0 / Read the vector
move.b d0,d1 / Save vector to retrieve status
lsr.b $1,d0 / Discard least significant bit
andi.w $0x7c,d0 / Isolate channel number (and make word)
eori.w $0x04,d0 / Toggle A/B channel bit
lea sccchan_,a0 / Address SCC channel table
movea.l 0(a0,d0),a0 / Read address of channel structure
move.l a0,d0 / Make sure this is an attached channel
beq.s panic / No channel struct, problems...
andi.w $0x06,d1 / Isolate status info from vector
lsl.w $1,d1 / Make index in LONG array
movea.l 0(a0,d1),a1 / Read the interrupt handler address
/
/ Call the handler (defined in C), with sccchan struct as a parameter
/
move.l a0,-(sp) / Put channel struct as a parameter
jsr (a1) / Call the handler
addq.l $4,sp / Remove parameter
/
/ Clear the ISR bit in the MFP
/
clrisrnv:
movea.l sccisrloc_,a0 / Location of ISR
move.w sccisrbit_,d0 / Bit number to clear
bclr d0,(a0) / Clear the bit
/
/ Determine if more interrupt requests are coming in from the SCCs
/
movea.l sccgpiploc_,a0 / Location of GPIP register
move.w sccgpipbit_,d0 / Bit number to test
btst d0,(a0) / Test bit in GPIP data register
beq.s sccintnv / Is active, handle next SCC interrupt
/
/ Restore registers and return from interrupt handler
/
movem.l (sp)+,${d0-d2,a0-a2} / Restore registers
rte
/
/
/ This routine will be inserted in the 200Hz timer interrupt handling
/ (vector 0x114) to call the SCC driver timing routine every 2nd
/ interrupt (= every 10 ms), and thereafter jump to the original handler
/
scctvec_:
btst $0,0x4bd / Test low bit of 200Hz counter
beq.s punt / Not our turn
movem.l ${d0-d2,a0-a2},-(sp) / Save C working registers
jsr scctim_ / Call C routine every 10 ms
movem.l (sp)+,${d0-d2,a0-a2} / Restore registers
punt: jmp 0xeeeeeeee / Jump to original handler
sccotvec_ = .-4 / Original hander address stored here